package client;

import info.clearthought.layout.TableLayout;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

import utils.Settings;

import commands.CommandNewTable;
import components.RPSButton;
import components.RPSCheckBox;
import components.RPSPanel;

/**
 * This class is the options dialog that opens when a user creates a new table.
 */
public class NewGameSettingsDialog extends JDialog
{
	private static final long serialVersionUID = 1L;
	
	private static final String FRAME_TITLE = "Game Options";
	private static final int SPACING = 5;
	
	// Time per-turn
	private RPSCheckBox checkBoxLimitTurnTime = null;
	private JTextField textFieldTurnTime = null;
	private JLabel labelTurnTimeSeconds = null;
	
	// Will enemy weapons be shown after battle
	private RPSCheckBox checkBoxShowEnemyWeaponsAfterBattle = null;
	
	// Allow viewers see unrevealed weapons
	private RPSCheckBox checkBoxAllowViewersSeeUnrevealedWeapons = null;
	
	// OK-Cancel buttons
	private RPSButton buttonOK = null;
	private RPSButton buttonCancel = null;
	
	private IGameConnection conn;

	
    public NewGameSettingsDialog (Frame owner , IGameConnection conn)
    {
    	super(owner,true);
    	
    	this.conn = conn;
    	
    	setTitle(FRAME_TITLE);
		getContentPane().add(createNewGameOptionsPanel());
		pack();
		setResizable(false);
		
	    Dimension ownerSize = owner.getSize(); //getToolkit().getScreenSize();
		setLocation((int)ownerSize.getWidth() / 2 - this.getWidth() / 2 + owner.getLocation().x,
					(int)(ownerSize.getHeight() - this.getHeight()) / 5 + owner.getLocation().y);
	} 

    
    private RPSPanel createNewGameOptionsPanel()
    {
	    double pref = TableLayout.PREFERRED;
	    double fill = TableLayout.FILL;
	    
    	double[][] sizes = new double[][] { {fill}, {SPACING, fill, SPACING, fill, SPACING, fill, SPACING * 3, fill, SPACING} };
    	RPSPanel panelNewGameOptions = new RPSPanel(new TableLayout(sizes));
    	
    	// Time per-turn
    	sizes = new double[][] { {pref, SPACING, pref, SPACING, pref, SPACING}, {pref} };
    	RPSPanel panelTurnTime = new RPSPanel(new TableLayout(sizes));
    	checkBoxLimitTurnTime = new RPSCheckBox("Each turn will be limited to");
    	checkBoxLimitTurnTime.setSelected(GameSettings.PROPERTY_DEFAULT_VALUE_DOES_LIMIT_TURN_TIME);
    	textFieldTurnTime = new JTextField(GameSettings.PROPERTY_DEFAULT_VALUE_TURN_TIME_LIMIT_SECONDS, 4);
    	labelTurnTimeSeconds = new JLabel("seconds");
    	panelTurnTime.add(checkBoxLimitTurnTime	, "0, 0");
    	panelTurnTime.add(textFieldTurnTime		, "2, 0");
    	panelTurnTime.add(labelTurnTimeSeconds	, "4, 0");

    	// Will enemy weapons be shown after battle
    	sizes = new double[][] { {pref}, {pref} };
    	checkBoxShowEnemyWeaponsAfterBattle = new RPSCheckBox("Show enemy weapons after battle");
    	checkBoxShowEnemyWeaponsAfterBattle.setSelected(GameSettings.PROPERTY_DEFAULT_VALUE_DOES_SHOW_ENEMY_WEPAONS_AFTER_BATTLE);
    	
    	// Allow viewers see unrevealed weapons
    	checkBoxAllowViewersSeeUnrevealedWeapons = new RPSCheckBox("Allow viewers see unrevealed weapons");
    	checkBoxAllowViewersSeeUnrevealedWeapons.setSelected(GameSettings.PROPERTY_DEFAULT_VALUE_DOES_ALLOW_VIEWERS_SEE_UNREVEALED_WEAPONS);
    	
    	// OK-Cancel buttons
    	sizes = new double[][] { {SPACING, pref, SPACING, pref}, {pref} };
    	RPSPanel panelOKCancelButtons = new RPSPanel(new TableLayout(sizes));
    	buttonOK = new RPSButton("OK");
    	buttonCancel = new RPSButton("Cancel");	
    	panelOKCancelButtons.add(buttonOK, "1, 0");
    	panelOKCancelButtons.add(buttonCancel, "3, 0");

    	panelNewGameOptions.add(panelTurnTime, "0, 1");
    	panelNewGameOptions.add(checkBoxShowEnemyWeaponsAfterBattle, "0, 3");
    	panelNewGameOptions.add(checkBoxAllowViewersSeeUnrevealedWeapons, "0, 5");
    	panelNewGameOptions.add(panelOKCancelButtons, "0, 7, l, b");
    	
    	addListeners();
    	
    	buttonOK.grabFocus();
    	
    	return panelNewGameOptions;
    }

	private void addListeners()
	{
		buttonOK.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e)
			{
				if (validateInput())
				{
					GameSettings gameSettings = new GameSettings();
					
					setSettings(gameSettings);
					
					CommandNewTable cmdNewTable = new CommandNewTable(conn.getUsername(), conn.getExternalIP(), gameSettings); //, PlayerColor.RED);
					conn.send(cmdNewTable);
					dispose();
				}
			}
		});
    	
    	buttonCancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e)
			{
				dispose();
			}
		});
    	
    	checkBoxLimitTurnTime.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e)
			{
				textFieldTurnTime.setEnabled(checkBoxLimitTurnTime.isSelected());
			}
		});
	}
	
	private boolean validateInput()
	{
		String errorMessage = "";
		String newLine = Settings.NEW_LINE; // For shortening
		boolean isValid = true;
		
		if (textFieldTurnTime.isEnabled())
		{
			// Check that the number of seconds is a positive integer
			if (textFieldTurnTime.getText().isEmpty())
			{
				errorMessage += "You must enter the number of seconds per turn or deselct the option." + newLine;
			}
			else
			{
				int turnTimeSeconds = -1;
				
				try
				{
					turnTimeSeconds = Integer.parseInt(textFieldTurnTime.getText().trim());
					
					if (turnTimeSeconds < Settings.MIN_SECONDS_PER_TURN)
					{
						errorMessage += "The number of seconds per turn must be at least " + Settings.MIN_SECONDS_PER_TURN + "." + newLine;
					}
				}
				catch (NumberFormatException e)
				{
					errorMessage += "The number of seconds per turn must be an Integer." + newLine;
				}
			}
		}
		
		// Remove the last new line and show a message box to the user
		if (errorMessage.isEmpty() == false)
		{
			isValid = false;
			// Remove the new-line at the end of the last line from the validation message
			errorMessage = errorMessage.substring(0, errorMessage.length() - newLine.length());
			JOptionPane.showMessageDialog(conn.getClientFrame(), errorMessage, "Input Validation", JOptionPane.ERROR_MESSAGE);
		}
		
		return isValid;
	}
	
	private void setSettings(GameSettings gameSettings)
	{
		gameSettings.setSetting(GameSettings.PROPERTY_KEY_DOES_LIMIT_TURN_TIME, String.valueOf(checkBoxLimitTurnTime.isSelected()));
		gameSettings.setSetting(GameSettings.PROPERTY_KEY_TURN_TIME_LIMIT_SECONDS, checkBoxLimitTurnTime.isSelected() ? textFieldTurnTime.getText() : "");
		gameSettings.setSetting(GameSettings.PROPERTY_KEY_DOES_SHOW_ENEMY_WEAPONS_AFTER_BATTLE, String.valueOf(checkBoxShowEnemyWeaponsAfterBattle.isSelected()));
		gameSettings.setSetting(GameSettings.PROPERTY_KEY_DOES_ALLOW_VIEWERS_SEE_UNREVEALED_WEAPONS, String.valueOf(checkBoxAllowViewersSeeUnrevealedWeapons.isSelected()));
	}

	public void showCurrentSettings(GameSettings gameSettings)
	{
		buttonCancel.setText("Close");
		buttonOK.setVisible(false);

		checkBoxLimitTurnTime.setEnabled(false);
		labelTurnTimeSeconds.setForeground(new Color(110, 110, 110));
		textFieldTurnTime.setEnabled(false);
		checkBoxShowEnemyWeaponsAfterBattle.setEnabled(false);
		checkBoxAllowViewersSeeUnrevealedWeapons.setEnabled(false);
		
		checkBoxLimitTurnTime.setSelected(Boolean.parseBoolean(gameSettings.getSetting(GameSettings.PROPERTY_KEY_DOES_LIMIT_TURN_TIME)));
		textFieldTurnTime.setText(gameSettings.getSetting(GameSettings.PROPERTY_KEY_TURN_TIME_LIMIT_SECONDS));
		checkBoxShowEnemyWeaponsAfterBattle.setSelected(Boolean.parseBoolean(gameSettings.getSetting(GameSettings.PROPERTY_KEY_DOES_SHOW_ENEMY_WEAPONS_AFTER_BATTLE)));
		checkBoxAllowViewersSeeUnrevealedWeapons.setSelected(Boolean.parseBoolean(gameSettings.getSetting(GameSettings.PROPERTY_KEY_DOES_ALLOW_VIEWERS_SEE_UNREVEALED_WEAPONS)));
		
		setVisible(true);
		validate();
	}
}
